package cn.iocoder.yudao.module.design.service.house;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.design.controller.admin.house.vo.*;
import cn.iocoder.yudao.module.design.controller.admin.relativednc.vo.RelativedNcCreateReqVO;
import cn.iocoder.yudao.module.design.controller.common.HdFlowCdItemVo;
import cn.iocoder.yudao.module.design.convert.house.HouseConvert;
import cn.iocoder.yudao.module.design.dal.dataobject.flow.FlowDO;
import cn.iocoder.yudao.module.design.dal.dataobject.flowmd.FlowMdDO;
import cn.iocoder.yudao.module.design.dal.dataobject.flowtask.FlowTaskDO;
import cn.iocoder.yudao.module.design.dal.dataobject.house.HouseDO;
import cn.iocoder.yudao.module.design.dal.dataobject.houseUserRel.HouseUserRelDO;
import cn.iocoder.yudao.module.design.dal.dataobject.node.NodeDO;
import cn.iocoder.yudao.module.design.dal.dataobject.pic.PicDO;
import cn.iocoder.yudao.module.design.dal.dataobject.problem.ProblemDO;
import cn.iocoder.yudao.module.design.dal.dataobject.relatived.RelativedDO;
import cn.iocoder.yudao.module.design.dal.dataobject.userflowrel.UserFlowRelDO;
import cn.iocoder.yudao.module.design.dal.mysql.flow.FlowMapper;
import cn.iocoder.yudao.module.design.dal.mysql.flowmd.FlowMdMapper;
import cn.iocoder.yudao.module.design.dal.mysql.flowtask.FlowTaskMapper;
import cn.iocoder.yudao.module.design.dal.mysql.house.HouseMapper;
import cn.iocoder.yudao.module.design.dal.mysql.houseUserRel.HouseUserRelMapper;
import cn.iocoder.yudao.module.design.dal.mysql.node.NodeMapper;
import cn.iocoder.yudao.module.design.dal.mysql.pic.PicMapper;
import cn.iocoder.yudao.module.design.dal.mysql.problem.ProblemMapper;
import cn.iocoder.yudao.module.design.dal.mysql.relatived.RelativedMapper;
import cn.iocoder.yudao.module.design.dal.mysql.userflowrel.UserFlowRelMapper;
import cn.iocoder.yudao.module.design.service.flowtask.FlowTaskService;
import cn.iocoder.yudao.module.design.service.house.bo.NodeItemDataBO;
import cn.iocoder.yudao.module.design.service.houseUserRel.HouseUserRelService;
import cn.iocoder.yudao.module.design.service.node.NodeService;
import cn.iocoder.yudao.module.design.service.pic.PicService;
import cn.iocoder.yudao.module.design.service.problem.ProblemService;
import cn.iocoder.yudao.module.design.service.relativednc.RelativedNcService;
import cn.iocoder.yudao.module.system.controller.admin.dict.vo.data.DictDataSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.dict.DictTypeDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.dict.DictTypeMapper;
import cn.iocoder.yudao.module.design.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.design.enums.design.*;
import cn.iocoder.yudao.module.design.enums.user.DesignUserRoleEnum;
import cn.iocoder.yudao.module.system.service.dict.DictDataService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.design.enums.ErrorCodeConstants.HOUSE_NOT_EXISTS;
import static cn.iocoder.yudao.module.design.enums.ErrorCodeConstants.QUERY_NOT_EXISTS;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.DICT_TYPE_NOT_ENABLE;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.DICT_TYPE_NOT_EXISTS;

/**
 * 装修的房子信息 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
@Slf4j
@Lazy
public class HouseServiceImpl implements HouseService {

    @Resource
    private RelativedMapper relativedMapper;
    @Resource
    private HouseMapper houseMapper;
    @Resource
    private PicMapper picMapper;
    @Resource
    private FlowMapper flowMapper;

    @Resource
    private HouseUserRelService houseUserRelService;
    @Resource
    private HouseUserRelMapper houseUserRelMapper;

    @Resource
    private ProblemMapper problemMapper;

    @Resource
    private FlowTaskMapper flowTaskMapper;

    @Resource
    private NodeMapper nodeMapper;


    @Resource
    private UserFlowRelMapper userFlowRelMapper;


    @Resource
    private FlowMdMapper flowMdMapper;

    @Resource
    private AdminUserService userService;


    @Resource
    private PermissionService permissionService;

    @Resource
    private RelativedNcService relativedNcService;

    @Resource
    private DictDataService dictDataService;

    @Resource
    private DictTypeMapper dictTypeMapper;
    @Resource
    private PicService picService;

    @Resource
    @Lazy
    private ProblemService problemService;

    @Resource
    @Lazy
    private FlowTaskService flowTaskService;

    @Resource
    @Lazy
    private NodeService nodeService;
    /**
     * 创建项目保存草稿
     * @param[1] HouseOneReqVO
     * @throws
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createBusinessHouse(HouseOneReqVO createReqVO) {
        // 插入 房子信息
        HouseDO house = HouseConvert.INSTANCE.convert(createReqVO);
        // 待发起
        house.setStatus(HouseStatusCdEnum.HOUSE_STATUS_CD_0.getCode().toString());
        house.setIzPay(YesNoEnum.YES_NO_ENUM_1.getCode());
        houseMapper.insert(house);
        return house.getId();
    }

    /**
     * 更新房子信息
     *
     * @param updateReqVO 更新信息
     */
    @Override
    public void updateBusinessHouse(HouseOneReqVO updateReqVO) {
        // 校验存在
        this.validateHouseExists(updateReqVO.getId());
        // 更新
        HouseDO updateObj = HouseConvert.INSTANCE.convert(updateReqVO);
        updateObj.setId(updateReqVO.getId());
        houseMapper.updateById(updateObj);

    }


    @Override
    @Transactional
    public Long createHouse(HouseCreateReqVO createReqVO) {
        // 默认当前创建人为设计师
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        createReqVO.setDesignerId(loginUserId);
        // 项目经理  & 材料管家为空 默认是当前创建人
        if(createReqVO.getProjectManagerId()==null){
            createReqVO.setProjectManagerId(loginUserId);
        }

        if(createReqVO.getStorekeeperId()==null){
            createReqVO.setStorekeeperId(loginUserId);
        }
        // 插入 房子信息
        HouseDO house = HouseConvert.INSTANCE.convert(createReqVO);
        house.setStatus("1");
        house.setIzPay(YesNoEnum.YES_NO_ENUM_1.getCode());
        houseMapper.insert(house);
        // 保存关联人信息
        saveAllHouseUserRel(house.getId(),createReqVO);
        PicDO picDo = new PicDO();
        picDo.setHouseId(house.getId());
        picDo.setUploadType("0");
        // 平面图
        picDo.setSourceType("7");
        // 保存图片文件
        picService.savePicData(picDo,createReqVO.getFileList());
        // 保存附件
        picDo.setUploadType("1");
        picDo.setSourceType("0");
        picService.savePicData(picDo,createReqVO.getDocList());
        // 创建流程模板
        createFlowByTemplate(house);

        saveFlowTask(house);


        // 返回
        return house.getId();
    }

    /**
     * @param createReqVO
     * @return
     */
    @Override
    public void addPicData(HouseUpdatePicDataReqVO createReqVO) {
        PicDO picDo = new PicDO();
        picDo.setHouseId(createReqVO.getId());
        picDo.setUploadType(createReqVO.getUploadType());
        picDo.setSourceType(StrUtil.isNotEmpty(createReqVO.getSourceType())?createReqVO.getSourceType():"0");
        // 保存图片文件
        picService.savePicData(picDo,createReqVO.getFileList());
    }

    public void saveFlowTask(HouseDO house){
        saveFlowTask(house,null);
    }

    @Override
    public void saveFlowTask(HouseDO house,Integer flowCd){
        // 查询 设计流程信息
        QueryWrapper  query = new QueryWrapper();
        query.eq("house_id",house.getId());
        if(ObjectUtil.isNotEmpty(flowCd)){
            query.eq("flow_cd",flowCd);

        }
        query.eq("status_cd",FlowStatusEnum.FLOW_STATUS_ENUM_1.getCode());

       List<FlowDO> flowDOList = flowMapper.selectList(query);
        for (FlowDO flowDO:flowDOList     ) {


            // 建立项目简介
            QueryWrapper  queryNode = new QueryWrapper();
            queryNode.eq("house_id",house.getId());
            queryNode.eq("flow_id",flowDO.getId());
            queryNode.eq("pre_id",0);
            queryNode.eq("sort_id",1);
            queryNode.eq("status_cd",0);
            NodeDO nodeDO = nodeMapper.selectOne(queryNode);



            // 创建开工信息补充提醒
            FlowTaskDO flowTaskDO = new FlowTaskDO();
            flowTaskDO.setTaskName("任务处理");
            flowTaskDO.setHouseId(house.getId());
            flowTaskDO.setProjectName(house.getProjectName());
            flowTaskDO.setFlowId(flowDO.getId());
            flowTaskDO.setFlowName(flowDO.getFlowName());
            flowTaskDO.setNodeId(nodeDO.getId());
            flowTaskDO.setNodeName(nodeDO.getNodeName());
            //,0-待开始1-进行中，2-已完成',
            flowTaskDO.setStatusCd(FlowTaskStatusEnum.FLOW_STATUS_ENUM_1.getCode());
            if(FlowCdEnum.FLOW_CD_0.getCode().equals(flowDO.getFlowCd())){
                flowTaskDO.setDealerId(SecurityFrameworkUtils.getLoginUserId());
                // 单独赋值
                flowTaskDO.setPreId(0L);
            }else if(FlowCdEnum.FLOW_CD_1.getCode().equals(flowDO.getFlowCd())){
                // 采购流程 选择对应的供应商
                // 查询供应商信息
                Map supplierInfo = userFlowRelMapper.selectUserRelInfoByRoleId(flowDO.getId(), DesignUserRoleEnum.SUPPLIER.getRoleId());
                flowTaskDO.setDealerId((Long) supplierInfo.get("id"));
                flowTaskDO.setStatusCd(FlowTaskStatusEnum.FLOW_STATUS_ENUM_0.getCode());
            }else if(FlowCdEnum.FLOW_CD_2.getCode().equals(flowDO.getFlowCd())){
                Map projectManager = userFlowRelMapper.selectUserRelInfoByRoleId(flowDO.getId(), DesignUserRoleEnum.PROJECT_MANAGER.getRoleId());
                flowTaskDO.setDealerId((Long) projectManager.get("id"));
                flowTaskDO.setStatusCd(FlowTaskStatusEnum.FLOW_STATUS_ENUM_0.getCode());
            }
            // 0-补充信息 1-任务流转
            flowTaskDO.setTaskType(FlowTaskTypeEnum.FLOW_TASk_CD_1.getCode().toString());
            flowTaskDO.setStartTime(new Date());
            flowTaskDO.setDeleted(false);
            flowTaskDO.setFlowCd(flowDO.getFlowCd());
            flowTaskMapper.insert(flowTaskDO);


            //将当前节点 置为进行中
            nodeDO.setStatusCd(NodeStatusEnum.NODE_STATUS_ENUM_1.getCode().toString());
            nodeMapper.updateById(nodeDO);
        }
    }
/**
 * 保存人员流程关系数据
 */
public void saveHouseUserFlowRel(Long houseId ,Long flowId ,Long userId ,Long roleId){
    // 判断 house_id flow_id user_id role_id 是否存在 status = 0 则修改  不存在新增
    QueryWrapper  queryWrapper = new QueryWrapper();
    queryWrapper.eq("house_id",houseId);
    queryWrapper.eq("flow_id",flowId);
    queryWrapper.eq("user_id",userId);
    queryWrapper.eq("role_id",roleId);
    queryWrapper.in("status",UserFlowRelStatusCdEnum.USER_REL_STATUS_CD_0.getCode(),UserFlowRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode());
    Long aLong = userFlowRelMapper.selectCount(queryWrapper);
    if(aLong>0){
        log.info("已存在对应流程数据，无需新增");
        return ;
    }

    // 保存用户流程关系
    UserFlowRelDO  userFlowRelDO     = new UserFlowRelDO();
    userFlowRelDO.setHouseId(houseId);
    userFlowRelDO.setFlowId(flowId);
    userFlowRelDO.setUserId(userId);
    userFlowRelDO.setRoleId(roleId);
    userFlowRelDO.setStatus(UserFlowRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode().toString());
   userFlowRelMapper.insert(userFlowRelDO);
}
    /**
     * 对关联人发起项目关联请求
     */
    public void saveHouseUserRelTask(Long houseId,String projectName,Long userId,Long roleId){
        saveHouseUserRelTask(houseId,projectName,userId,roleId,
                UserRelStatusCdEnum.USER_REL_STATUS_CD_0.getCode());
    }
    /**
     * 对关联人发起项目关联请求
     * statusCd 0 待开始  1 进行中 2 完成
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveHouseUserRelTask(Long houseId,String projectName,Long userId,Long roleId,Integer statusCd){
        final Long loginUserId = SecurityFrameworkUtils.getLoginUserId();

        if(String.valueOf(loginUserId).equals(String.valueOf(userId))){
            log.debug("处理人与登录人相同 则不建立申请任务");
            return;
        }
        // 判断当前人员在当前项目中是否已经关联  已关联则不发任务直接添加
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("house_id",houseId);
        queryWrapper.eq("user_id",userId);
        // 关联人处理的时候是 roleId = flowCd
        queryWrapper.in("status", UserRelStatusCdEnum.USER_REL_STATUS_CD_0.getCode(),
                UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode());
        Long userRelCount = houseUserRelMapper.selectCount(queryWrapper);
        if(userRelCount>0L){
            HouseUserRelDO houseUserRel = new HouseUserRelDO();
            houseUserRel.setHouseId(houseId);
            houseUserRel.setUserId(userId);
            houseUserRel.setRoleId(roleId);
            houseUserRel.setStatus(UserRelStatusCdEnum.USER_REL_STATUS_CD_0.getCode().toString());
            houseUserRel.setDeleted(false);
            houseUserRelMapper.insert(houseUserRel);
            statusCd = 2;
        }

        final AdminUserDO user = userService.getUser(loginUserId);
        FlowTaskDO flowTaskDO = new FlowTaskDO();
        flowTaskDO.setTaskName("项目关联申请");
        flowTaskDO.setHouseId(houseId);
        flowTaskDO.setProjectName(projectName);
        flowTaskDO.setDealerId(userId);
        // 0-补充信息 1-任务流转 2-项目关联申请
        flowTaskDO.setTaskType(FlowTaskTypeEnum.FLOW_TASk_CD_2.getCode().toString());
        //1-进行中，2-已完成',
        flowTaskDO.setStatusCd(statusCd);
        flowTaskDO.setStartTime(new Date());
        flowTaskDO.setDeleted(false);
        flowTaskDO.setFlowCd(Integer.valueOf(Math.toIntExact(roleId)));  // 暂存角色字段
        String remark = user.getNickname()+"  邀请你加入 【 " +projectName+" 】 项目";
        flowTaskDO.setRemark(remark);
        flowTaskDO.setCreator(loginUserId.toString());
        flowTaskMapper.insert(flowTaskDO);

    }


    /**
     * 根据数据库模板新建流程
     */
    @Transactional(rollbackFor = Exception.class)
    public void createFlowByTemplate(HouseDO house){
        // 模板新建
        Long houseId =house.getId();
        // 查询项目关联人关系
        QueryWrapper queryUserRel = new QueryWrapper();
        queryUserRel.eq("house_id",houseId);

        queryUserRel.in("status","0","1");

        List<HouseUserRelDO> userRelList = houseUserRelMapper.selectList(queryUserRel);
        // 获取项目中项目经理Id
        List<Long> projectIds = userRelList.stream()
                .filter(userRelDO -> userRelDO.getRoleId().equals( DesignUserRoleEnum.PROJECT_MANAGER.getRoleId()))
                .map(HouseUserRelDO::getUserId)
                .collect(Collectors.toList());
        // 获取项目中项目经理Id
        List<Long> supplierIds = userRelList.stream()
                .filter(userRelDO -> userRelDO.getRoleId().equals( DesignUserRoleEnum.SUPPLIER.getRoleId()))
                .map(HouseUserRelDO::getUserId)
                .collect(Collectors.toList());
        // 新建设计流程
        FlowDO designFlow = new FlowDO();
        designFlow.setFlowName("设计流程");
        designFlow.setHouseId(houseId);
        designFlow.setIsMainCd("0");
        designFlow.setStatusCd(FlowStatusEnum.FLOW_STATUS_ENUM_1.getCode());
        designFlow.setFlowCd(FlowCdEnum.FLOW_CD_0.getCode());
        designFlow.setDesignerId(house.getDesignerId());
        designFlow.setDeleted(false);
        designFlow.setStartTime(new Date());
        designFlow.setCreator(SecurityFrameworkUtils.getLoginUserId().toString());
        designFlow.setRemark("系统生成设计流程");
        int count = flowMapper.insert(designFlow);
        if(count>0){
            createNodeByTemplate(houseId,designFlow.getId(),house.getDesignerId(),FlowCdEnum.FLOW_CD_0.getCode(), house.getDesignerId());
            // 保存业主和设计流程关系
            saveHouseUserFlowRel(houseId,designFlow.getId(),house.getOwnerId(),DesignUserRoleEnum.OWNER.getRoleId());
            // 保存设计师和设计流程关系
            saveHouseUserFlowRel(houseId,designFlow.getId(),house.getDesignerId(),DesignUserRoleEnum.DESIGN.getRoleId());
            // 保存客服设计流程关系
//            saveHouseUserFlowRel(houseId,designFlow.getId(),house.get(),DesignUserRoleEnum.OWNER.getRoleId());

        }

//        // 新建采购流程
            supplierIds.forEach((userId)->{
            FlowDO procurementFlow = new FlowDO();
            String nodeName = DateUtil.format(new Date(), "yyyyMMdd") + "-采购任务";


            procurementFlow.setFlowName(nodeName);
            procurementFlow.setHouseId(houseId);
            procurementFlow.setIsMainCd("0");
            procurementFlow.setStatusCd(FlowStatusEnum.FLOW_STATUS_ENUM_1.getCode());
            procurementFlow.setFlowCd(FlowCdEnum.FLOW_CD_1.getCode());
            procurementFlow.setStartTime(new Date());
            procurementFlow.setDesignerId(house.getDesignerId());
            procurementFlow.setDeleted(false);
            procurementFlow.setCreator(SecurityFrameworkUtils.getLoginUserId().toString());
            procurementFlow.setRemark(nodeName);
            int count1 = flowMapper.insert(procurementFlow);
            if(count1>0){

                createNodeByTemplate(houseId,procurementFlow.getId(),house.getDesignerId(),FlowCdEnum.FLOW_CD_1.getCode(),userId);
                // 保存供应商 和流程的关联关系
                saveHouseUserFlowRel(houseId,procurementFlow.getId(),userId,DesignUserRoleEnum.SUPPLIER.getRoleId());
                // 保存业主和采购流程关系
                saveHouseUserFlowRel(houseId,procurementFlow.getId(),house.getOwnerId(),DesignUserRoleEnum.OWNER.getRoleId());
                // 保存设计师和采购流程关系
                saveHouseUserFlowRel(houseId,procurementFlow.getId(),house.getDesignerId(),DesignUserRoleEnum.DESIGN.getRoleId());
            }

        });

        // 新建施工流程
        FlowDO constructionFlow = new FlowDO();
        constructionFlow.setFlowName("施工流程");
        constructionFlow.setHouseId(houseId);
        constructionFlow.setIsMainCd("0");
        constructionFlow.setStatusCd(FlowStatusEnum.FLOW_STATUS_ENUM_0.getCode());
        constructionFlow.setFlowCd(FlowCdEnum.FLOW_CD_2.getCode());
        constructionFlow.setDesignerId(house.getDesignerId());
        constructionFlow.setDeleted(false);
        constructionFlow.setCreator(SecurityFrameworkUtils.getLoginUserId().toString());
        constructionFlow.setRemark("系统生成施工流程");
        int count2 = flowMapper.insert(constructionFlow);
        if(count2>0){

            // 保存业主和施工流程关系
            saveHouseUserFlowRel(houseId,constructionFlow.getId(),house.getOwnerId(),DesignUserRoleEnum.OWNER.getRoleId());
            // 保存设计师和施工流程关系
            saveHouseUserFlowRel(houseId,constructionFlow.getId(),house.getDesignerId(),DesignUserRoleEnum.DESIGN.getRoleId());
            // 保存项目经理和施工流程关系
            projectIds.forEach(userId->{
                saveHouseUserFlowRel(houseId,constructionFlow.getId(),userId,DesignUserRoleEnum.PROJECT_MANAGER.getRoleId());
            });


        }
    }
    @Override
    public void createPurchaseFLow(HouseDO house,Long userId,String orgName){
        FlowDO procurementFlow = new FlowDO();
        String nodeName =  orgName+ "-采购任务";


        procurementFlow.setFlowName(nodeName);
        procurementFlow.setHouseId(house.getId());
        procurementFlow.setIsMainCd("0");
        procurementFlow.setStatusCd(FlowStatusEnum.FLOW_STATUS_ENUM_1.getCode());
        procurementFlow.setFlowCd(FlowCdEnum.FLOW_CD_1.getCode());
        procurementFlow.setStartTime(new Date());
        procurementFlow.setDesignerId(house.getDesignerId());
        procurementFlow.setDeleted(false);
        procurementFlow.setCreator(SecurityFrameworkUtils.getLoginUserId().toString());
        procurementFlow.setRemark(nodeName);
        int count1 = flowMapper.insert(procurementFlow);
        if(count1>0){

            createNodeByTemplate(house.getId(),procurementFlow.getId(),house.getDesignerId(),FlowCdEnum.FLOW_CD_1.getCode(), userId);
            // 保存供应商 和流程的关联关系
            saveHouseUserFlowRel(house.getId(),procurementFlow.getId(),userId,DesignUserRoleEnum.SUPPLIER.getRoleId());
            // 保存业主和采购流程关系
            saveHouseUserFlowRel(house.getId(),procurementFlow.getId(),house.getOwnerId(),DesignUserRoleEnum.OWNER.getRoleId());
            // 保存设计师和采购流程关系
            saveHouseUserFlowRel(house.getId(),procurementFlow.getId(),house.getDesignerId(),DesignUserRoleEnum.DESIGN.getRoleId());
        }
    }
    @Transactional(rollbackFor = Exception.class)
    public void createNodeByTemplate(Long houseId, Long flowId, Long designerId, Integer flowCd,Long dealerId){
        createNodeByTemplate(houseId,flowId,designerId,flowCd,dealerId,null);
    }
    @Transactional(rollbackFor = Exception.class)
    public void createNodeByTemplate(Long houseId, Long flowId, Long designerId, Integer flowCd,Long dealerId,Collection<Long> flowMdIds){
        // 查询模板数据
         QueryWrapper<FlowMdDO> objectQueryWrapper = new QueryWrapper<FlowMdDO>();
         objectQueryWrapper.eq("flow_cd",flowCd);
         if("1".equals(flowCd)){
             objectQueryWrapper.eq("id",4);
         }
//         objectQueryWrapper.orderByDesc("id");
        // TODO  根据传入的ID  查询对应的流程-> 然后在根据传入的id 集合 筛选子项 Children
         List<FlowMdDO> list =flowMdMapper.selectList(objectQueryWrapper);
        NodeItemDataBO context = new NodeItemDataBO();
        context.setHouseId(houseId);
        context.setFlowId(flowId);
        context.setDesignerId(designerId);
        context.setFlowCd(flowCd);
        context.setList(list);
        context.setDealerId(dealerId);
        context.setFlowMdIds(flowMdIds);
        saveNodeItemData(context);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveNodeItemData(NodeItemDataBO context){
        // 因为采购 施工 模板详情 为详细列表模式 没有sortId 所以目前使用 程序累加  后续在改
        int index = 1 ;

        if("2".equals(context.getFlowCd())&& context.getFlowMdIds()!=null){
            // 判断是否施工勾选进入  是则需要寻找index 最大值
            // 不然会在项目流转的时候找到多个sort为1 的数据导致报错
            QueryWrapper queryWrap = new QueryWrapper();
            queryWrap.eq("house_id",context.getHouseId());
            queryWrap.eq("flow_id",context.getFlowId());
            queryWrap.eq("pre_id",0L);
            index = Math.toIntExact(nodeMapper.selectCount(queryWrap));
            index++;
        }
        Integer sgDays = 0;
        for (FlowMdDO item:context.getList()) {

            Long preId = 0L;

            // 采购任务
//            if("1".equals(flowCd)){
//                NodeDO nodeDO = new NodeDO();
//                nodeDO.setPreId(preId);
//                nodeDO.setFlowId(flowId);
//                nodeDO.setHouseId(houseId);
//                nodeDO.setSortId(String.valueOf(index));
//                nodeDO.setDesignerId(designerId);
//                nodeDO.setDealerId(dealerId);
//                nodeDO.setFlowDtlCd(item.getFlowDtlCd());
//                nodeDO.setNodeName(item.getFlowName());
//                nodeDO.setStartTime(new Date());
//                // 进行中
//                nodeDO.setStatusCd("1");
//                nodeDO.setRemark("");
//                nodeDO.setSortId(String.valueOf(index));
//                nodeDO.setCreator(SecurityFrameworkUtils.getLoginUserId().toString());
//                nodeDO.setDeleted(false);
//                nodeMapper.insert(nodeDO);
//
//                preId = nodeDO.getId();
//                index++;
//            }
             // 施工任务
            if(FlowCdEnum.FLOW_CD_2.getCode().equals(context.getFlowCd())){
                Collection<NodeDO> optionData = context.getOptionData();
                NodeDO nodeDO = new NodeDO();
                nodeDO.setPreId(preId);
                nodeDO.setFlowId(context.getFlowId());
                nodeDO.setHouseId(context.getHouseId());
                nodeDO.setSortId(String.valueOf(index));
                nodeDO.setDesignerId(context.getDesignerId());
                nodeDO.setFlowDtlCd(item.getFlowDtlCd());
                nodeDO.setNodeName(item.getFlowName());
                nodeDO.setStartTime(new Date());
                // 待开始
                nodeDO.setStatusCd("0");
                nodeDO.setRemark("自动生成节点");
                nodeDO.setSortId(String.valueOf(index));
                nodeDO.setCreator(SecurityFrameworkUtils.getLoginUserId().toString());
                nodeDO.setDeleted(false);
                Integer days = findDaysByFlowMdId(item.getId(), optionData);

                sgDays = sgDays+days ;
                nodeDO.setDays(days);
                nodeMapper.insert(nodeDO);

                preId = nodeDO.getId();
                index++;
            }
            // 保存子节点信息
            if(StrUtil.isNotEmpty(item.getChildren())){
                saveNextIdsData( context.getFlowId(), context.getHouseId(), preId, context.getDesignerId(), item.getFlowDtlCd(),item.getChildren(),context.getFlowMdIds());
            }


        }
//         施工流程 保存修改施工天数
        if(FlowCdEnum.FLOW_CD_2.getCode().equals(context.getFlowCd())){
            updateUnitTotalDays(context.getHouseId(),sgDays);

        }
    }

    /**
     * 启动项目
     *
     * @param houseId
     * @throws
     */
    @Override
    public void startHouseStatus(Long houseId,String payOrderId) {
        HouseDO houseDO = validateHouseExists(houseId);
        houseDO.setStatus(HouseStatusCdEnum.HOUSE_STATUS_CD_1.getCode().toString());
        houseDO.setPayOrderId(payOrderId);
        houseDO.setStartTime(new Date());
        houseMapper.updateById(houseDO);
    }

    @Override
    public void updateUnitTotalDays(Long houseId, Integer days) {
        HouseDO houseDO = validateHouseExists(houseId);
        houseDO.setUnitTotalDays(days);
        houseMapper.updateById(houseDO);
    }

    /**
     * 根据 flowMdId 查询前端上送的预计工期
     * 只查询施工大阶段的工期
     * @param flowMdId 模板id
     * @param optionData  前端填写的工期
     * @return day
     */
    public Integer findDaysByFlowMdId(Long flowMdId,  Collection<NodeDO> optionData ){
        if(ObjectUtil.isEmpty(flowMdId) &&  flowMdId.toString().length()!=6){
            return null;
        }
        Integer days = optionData.stream()
                .filter(object -> String.valueOf(flowMdId).equals(String.valueOf(object.getId())))
                .map(NodeDO::getDays)
                .filter(Objects::nonNull)
                .findFirst()
                .orElse(1);

        return days;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveNextIdsData(Long flowId,Long houseId,Long preId,Long designerId,String flowDtlCd, String nextIds){

        saveNextIdsData(flowId,houseId,preId,designerId,flowDtlCd,nextIds,null);
    }

    /**
     * 查询当前登录人在项目内所属角色
     *
     * @param houseId
     * @return List<String>
     * @author Annie
     * @time 2023/8/11 15:14
     * @param[1] houseId
     */
    @Override
    public List<String> getHouseRoles(Long houseId) {
        return null;
    }

    /**
     * 保存模板中nextIds 信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveNextIdsData(Long flowId,Long houseId,Long preId,Long designerId,String flowDtlCd, String nextIds,Collection<Long> flowMdIds){

        List<HdFlowCdItemVo> hdFlowCdItemVos = JSONUtil.toList(nextIds, HdFlowCdItemVo.class);
        int  index = 1;
        for (HdFlowCdItemVo itemVo :hdFlowCdItemVos
        ) {
            if(CollUtil.isNotEmpty(flowMdIds)){
                if(!flowMdIds.contains(Long.valueOf(itemVo.getId()))){
                   if(!isIncludedInJson(flowMdIds,itemVo.getChildren())){
                        continue;
                   }
                }
            }
            NodeDO nodeDO = new NodeDO();
            nodeDO.setPreId(preId);
            nodeDO.setFlowId(flowId);
            nodeDO.setFlowDtlCd(flowDtlCd);
            nodeDO.setHouseId(houseId);
            nodeDO.setDesignerId(designerId);
            nodeDO.setNextIds(itemVo.getItemIds());
            nodeDO.setSortId(String.valueOf(index));
            nodeDO.setNodeName(itemVo.getFlowName());
            nodeDO.setStartTime(new Date());
            // 带开始
            nodeDO.setStatusCd("0");
            nodeDO.setRemark("自动生成节点");
            nodeDO.setCreator(Objects.requireNonNull(SecurityFrameworkUtils.getLoginUserId()).toString());
            nodeDO.setDeleted(false);
            nodeDO.setPreRoleId(itemVo.getPreRoleId());
            nodeMapper.insert(nodeDO);
            index++;
            if(StrUtil.isNotEmpty(itemVo.getChildren())){
                saveNextIdsData( flowId, houseId, nodeDO.getId(), designerId, flowDtlCd,itemVo.getChildren(),flowMdIds);
            }
        }
    }

    /**
     * 判断长整型集合中的元素是否在 JSON 数组中
     */
    public static boolean isIncludedInJson(Collection<Long>  longList, String jsonStr) {

        List<HdFlowCdItemVo> hdFlowCdItemVos = JSONUtil.toList(jsonStr, HdFlowCdItemVo.class);
        for (HdFlowCdItemVo obj : hdFlowCdItemVos) {
            Long id1 = Long.valueOf(String.valueOf(obj.getId()));
            if (longList.contains(id1)) {
                return true;
            }
            if(StrUtil.isNotEmpty(obj.getChildren())) {
                return isIncludedInJson(longList,obj.getChildren());
            }
        }
        return false;
    }


    /**
     * 保存住宅关联人 初始化权限
     */
//    @Transactional(rollbackFor = Exception.class)
    public void saveAllHouseUserRel(Long houseId,HouseBaseVO house){
        List<HouseUserRelDO> houseUserRelList =new ArrayList<>();
         String loginUserid = SecurityFrameworkUtils.getLoginUserId().toString();

        // 关联人信息-业主
        HouseUserRelDO houseUserRel = new HouseUserRelDO();
        if(house.getOwnerId()!=null){
            String status = loginUserid.equals(house.getOwnerId().toString())?"0":"1";
            houseUserRel.setHouseId(houseId);
            houseUserRel.setUserId(house.getOwnerId());
            houseUserRel.setStatus(status);
            houseUserRel.setAddFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setRemoveFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setModifyFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setQueryFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setRoleId(Long.valueOf(DesignUserRoleEnum.OWNER.getRoleId()));
            houseUserRelList.add(houseUserRel);
            // 关联 业主
            saveHouseUserRelTask(houseId,house.getProjectName(),house.getOwnerId(),DesignUserRoleEnum.OWNER.getRoleId());
            // 关联流程
        }
            // 关联人信息-设计师
            String status1 = loginUserid.equals(house.getDesignerId().toString())?"0":"1";
            houseUserRel = new HouseUserRelDO();
            houseUserRel.setHouseId(houseId);
            houseUserRel.setUserId(house.getDesignerId());
            houseUserRel.setStatus(status1);
            houseUserRel.setAddFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setRemoveFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setModifyFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setQueryFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setRoleId(Long.valueOf(DesignUserRoleEnum.DESIGN.getRoleId()));
            houseUserRelList.add(houseUserRel);
            saveHouseUserRelTask(houseId,house.getProjectName(),house.getDesignerId(),DesignUserRoleEnum.DESIGN.getRoleId());

        // 关联人信息-项目经理
        if(house.getProjectManagerId()!=null) {
            String status = loginUserid.equals(house.getProjectManagerId().toString())?"0":"1";
            houseUserRel = new HouseUserRelDO();
            houseUserRel.setHouseId(houseId);
            houseUserRel.setStatus(status);
            houseUserRel.setUserId(house.getProjectManagerId());
            houseUserRel.setAddFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setRemoveFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setModifyFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setQueryFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setRoleId(Long.valueOf(DesignUserRoleEnum.PROJECT_MANAGER.getRoleId()));
            houseUserRelList.add(houseUserRel);
            // 关联 项目经理
            saveHouseUserRelTask(houseId,house.getProjectName(),house.getProjectManagerId(),DesignUserRoleEnum.PROJECT_MANAGER.getRoleId());
        }
        // 关联人信息-材料管理员
        if(house.getStorekeeperId()!=null) {
            String status = loginUserid.equals(house.getStorekeeperId().toString())?"0":"1";
            houseUserRel = new HouseUserRelDO();
            houseUserRel.setHouseId(houseId);
            houseUserRel.setUserId(house.getStorekeeperId());
            houseUserRel.setStatus(status);
            houseUserRel.setAddFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setRemoveFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setModifyFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setQueryFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setRoleId(Long.valueOf(DesignUserRoleEnum.STOREKEEPER.getRoleId()));
            houseUserRelList.add(houseUserRel);
            // 关联 材料管理员
            saveHouseUserRelTask(houseId,house.getProjectName(),house.getStorekeeperId(),DesignUserRoleEnum.STOREKEEPER.getRoleId());
        }

        // 关联人信息-客服
        if(house.getCustId()!=null) {
            String status = loginUserid.equals(house.getCustId().toString())?"0":"1";
            houseUserRel = new HouseUserRelDO();
            houseUserRel.setHouseId(houseId);
            houseUserRel.setStatus(status);
            houseUserRel.setUserId(house.getCustId());
            houseUserRel.setAddFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setRemoveFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setModifyFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setQueryFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
            houseUserRel.setRoleId(Long.valueOf(DesignUserRoleEnum.CUST_SERVICE.getRoleId()));
            houseUserRelList.add(houseUserRel);
            // 关联 客服
            saveHouseUserRelTask(houseId,house.getProjectName(),house.getCustId(),DesignUserRoleEnum.CUST_SERVICE.getRoleId());
        }

        // 关联人信息-供应商
        List<Long> suppliers = house.getSuppliers();
        if(CollUtil.isNotEmpty(suppliers)){
            for (Long userId:suppliers
            ) {
                String status = loginUserid.equals(userId.toString())?"0":"1";
                houseUserRel = new HouseUserRelDO();
                houseUserRel.setHouseId(houseId);
                houseUserRel.setUserId(userId);
                houseUserRel.setStatus(status);
                houseUserRel.setAddFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
                houseUserRel.setRemoveFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
                houseUserRel.setModifyFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
                houseUserRel.setQueryFlg(Long.valueOf(CommonStatusEnum.ENABLE.getStatus()));
                houseUserRel.setRoleId(Long.valueOf(DesignUserRoleEnum.SUPPLIER.getRoleId()));
                houseUserRelList.add(houseUserRel);
                // 关联 供应商
                saveHouseUserRelTask(houseId,house.getProjectName(),userId,DesignUserRoleEnum.SUPPLIER.getRoleId());
                // 供应商创建采购流程
            }
        }


        houseUserRelMapper.insertBatch(houseUserRelList);

    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateHouse(HouseUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateHouseExists(updateReqVO.getId());
        // 更新
        HouseDO updateObj = HouseConvert.INSTANCE.convert(updateReqVO);
        houseMapper.updateById(updateObj);

        // 先删除 对应关联人 再新增
        Map<String,Object> param = new HashMap<>();
        param.put("house_id",updateReqVO.getId());
         houseUserRelMapper.deleteByMap(param);
        saveAllHouseUserRel(updateReqVO.getId(),updateReqVO);
        // 保存图片
        PicDO picDo = new PicDO();
        picDo.setHouseId(updateReqVO.getId());
        // 平面图
        picDo.setUploadType("0");
        picDo.setSourceType("7");
        // 保存图片文件
        picService.savePicData(picDo,updateReqVO.getFileList());
        // 保存附件
        picDo.setUploadType("1");
        picDo.setSourceType("0");
        picService.savePicData(picDo,updateReqVO.getDocList());

    }

    @Override
    public void deleteHouse(Long id) {
        // 校验存在
        this.validateHouseExists(id);
        // 删除
        int delHouseCount = houseMapper.deleteById(id);
        if(delHouseCount>0){
            Map<String,Object> param = new HashMap<>();
            param.put("house_id",id);
            houseUserRelMapper.deleteByMap(param);
        }

    }
   @Override
    public HouseDO validateHouseExists(Long id) {
        HouseDO houseDO = houseMapper.selectById(id);
        if (houseDO == null) {
            throw exception(HOUSE_NOT_EXISTS);
        }
        return houseDO;
    }

    @Override
    public HouseDO getHouse(Long id) {
        return houseMapper.selectById(id);
    }
    @Override
    public HouseOneResVO getHouseOneById(Long id) {
        validateHouseExists(id);
        HouseDO houseDO = houseMapper.selectById(id);

        return HouseConvert.INSTANCE.convertHouseOne(houseDO);
    }
    /**
     * 获得装修的房子信息
     *
     * @param id 编号
     * @return 装修的房子信息
     */
    @Override
    public HouseRespVO getHouseById(Long id) {
        validateHouseExists(id);
        HouseDO houseDO = houseMapper.selectById(id);

        HouseRespVO convert = HouseConvert.INSTANCE.convert(houseDO);
        // 查询关联人
        getHouseUseRel(convert);
        // 查询上传附件,图片1
        PicDO picDO = new PicDO();
        picDO.setHouseId(houseDO.getId());
        picDO.setSourceType("7");
        picDO.setUploadType("0");
        List<PicDO> picData = picService.getPicData(picDO);
        convert.setFileList(picData);
        picDO.setUploadType("1");
        picDO.setSourceType("0");
        List<PicDO> picDocData = picService.getPicData(picDO);
        convert.setDocList(picDocData);
        // 判断是否可以修改 业主信息
        convert.setIsUpdate(true);
        // 查询施工流程id
        FlowDO flowDO = flowMapper.selectOne("house_id", id, "flow_cd", "2");
        if(flowDO==null){
            return convert;
        }
        // 查询 是否建立施工流程
        Long nodeCount = nodeMapper.selectCount("flow_id", flowDO.getId());
        if(nodeCount>0){
            convert.setIsUpdate(false);
        }


        return convert;
    }

    /**
     * 查询项目基本信息
     *
     * @param id 编号
     * @return 项目基本信息
     */
    @Override
    public HouseSimInfoVO getSimHouseInfo(Long id) {
        // 校验项目是否正确
        validateHouseExists(id);

        // 查询基本信息
        HouseDO houseDO = houseMapper.selectById(id);
        HouseSimInfoVO result = HouseConvert.INSTANCE.convertSimInfo(houseDO);

        // 查询问题数量  查询用户 待解决的问题 、已解决待处理的问题
        int problemCount = problemService.getProblemCount(id);
        // 查询待办数量
        int flowTaskCount = flowTaskService.getTaskCount(id);
        // 查询项目进度
        double buildProcess = nodeService.getBuildProcess(id);
        result.setProblemCount(problemCount);
        result.setTaskCount(flowTaskCount);
        result.setProjectProcess(buildProcess);
        return result;
    }

    public void getHouseUseRel(HouseRespVO houseRespVO){


        QueryWrapper<HouseUserRelDO> queryWrapper = new QueryWrapper<>();
        // 查询出所有关联人信息 根据roleId 赋值
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("house_id",houseRespVO.getId());
        queryWrapper.eq("deleted","0");
        queryWrapper.in("status","0","1");
        final List<HouseUserRelDO> houseUserRelDOS = houseUserRelMapper.selectList(queryWrapper);
        if(!houseUserRelDOS.isEmpty()){
            // 项目经理
            List<Long> projectList = houseUserRelDOS.stream()
                    .filter(house -> house.getRoleId().equals( DesignUserRoleEnum.PROJECT_MANAGER.getRoleId()))
                    .map(HouseUserRelDO::getUserId)
                    .distinct()
                    .collect(Collectors.toList());
            if(!projectList.isEmpty()){
                houseRespVO.setProjectManagerId(projectList.get(0)) ;
            }
            // 查询材料管理员
            List<Long> storekeeperList = houseUserRelDOS.stream()
                    .filter(house -> house.getRoleId().equals(DesignUserRoleEnum.STOREKEEPER.getRoleId()))
                    .map(HouseUserRelDO::getUserId)
                    .distinct()
                    .collect(Collectors.toList());
            if(!storekeeperList.isEmpty()){
                houseRespVO.setStorekeeperId(storekeeperList.get(0)) ;
            }

            // 查询客服
            List<Long> custList = houseUserRelDOS.stream()
                    .filter(house -> house.getRoleId().equals( DesignUserRoleEnum.CUST_SERVICE.getRoleId()))
                    .map(HouseUserRelDO::getUserId)
                    .distinct()
                    .collect(Collectors.toList());
            if(!custList.isEmpty()){
                houseRespVO.setCustId(custList.get(0)) ;
            }

            // 查询供应商
            List<Long> supplierList = houseUserRelDOS.stream()
                    .filter(house -> house.getRoleId().equals( DesignUserRoleEnum.SUPPLIER.getRoleId()))
                    .map(HouseUserRelDO::getUserId)
                    .distinct()
                    .collect(Collectors.toList());
            if(!supplierList.isEmpty()){
                houseRespVO.setSuppliers(supplierList);
            }
        }
    }
    @Override
    public List<HouseDO> getHouseList(Collection<Long> ids) {
        return houseMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<HouseDO> getHousePage(HousePageReqVO pageReqVO) {

        return houseMapper.selectPage(pageReqVO);
    }

    @Override
    public List<HouseDO> getHouseList(HouseExportReqVO exportReqVO) {
        return houseMapper.selectList(exportReqVO);
    }
    @Override
    public List<HouseRespVO> getHouseList(HouseBaseVO baseVO) {
        //  SecurityFrameworkUtils  getLoginUserRoleIds 获取当前用户角色 getLoginUser  获取当前用户  getLoginUserId  用户编号
        /*1.根据userId 查询hd_user_rel 中所有房子id  2. 根据查询的userId 查询房子信息*/
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        QueryWrapper<HouseUserRelDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",loginUser.getId());
        queryWrapper.eq("deleted","0");
        queryWrapper.eq("status","1");
        List<HouseUserRelDO> userIds = houseUserRelMapper.selectList(queryWrapper);

        List<Long> houseIds = userIds.stream().map(houseUserRelDO -> houseUserRelDO.getHouseId()).collect(Collectors.toList());


        // 平台管理员跳过 权限控制
        if(CollUtil.isEmpty(houseIds)){
              return new ArrayList<>();
        }

        // 根据权限控制 查询数据
        QueryWrapper<HouseDO> houseWrapper = new QueryWrapper<>();
        houseWrapper.in("id",houseIds);
        houseWrapper.eq("status","1");
        houseWrapper.eq("deleted","0");
        houseWrapper.orderByDesc("create_time");
        List<HouseDO> houseDoList = houseMapper.selectList(houseWrapper);


        // 查询附件数据
        List<HouseRespVO> houseRespList = HouseConvert.INSTANCE.convertList(houseDoList);
        for (HouseRespVO vo:houseRespList  ) {

            PicDO picDO = new PicDO();
            picDO.setHouseId(vo.getId());
            picDO.setSourceType("7");
            picDO.setUploadType("0");
            List<PicDO> picData = picService.getPicData(picDO);
            vo.setFileList(picData);
       		picDO.setSourceType("0");
            picDO.setUploadType("1");
            List<PicDO> picDocData = picService.getPicData(picDO);
            vo.setDocList(picDocData);
        }
        return houseRespList;
    }
    @Override
    public List<HouseDO> getHouseByStatus(Integer status) {
        return houseMapper.selectListByStatus(status);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUserRel(String nickName ,String mobile,String roleId) {
        HouseUserRelVO houseUserRelVO = new HouseUserRelVO();
        houseUserRelVO.setNickname(nickName);
        houseUserRelVO.setMobile(mobile);
        houseUserRelVO.setRoleId(roleId);
        return createUserRel(houseUserRelVO);
    }
    /**
     * 新增项目关联人并新增登录用户
     *
     * @param vo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUserRel(HouseUserRelVO vo) {
        //查询当前用户 的 部门   岗位
        final Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        final AdminUserDO loginUser = userService.getUser(loginUserId);
        // 校验手机号是否已创建
        final AdminUserDO userByMobile = userService.getUserByMobile(vo.getMobile());

        Long userId = null;
        Long roleId = Long.valueOf(vo.getRoleId());
        if(userByMobile==null){
            //  新增用户
            final UserSaveReqVO userCreateReqVO = new UserSaveReqVO();
            userCreateReqVO.setNickname(StrUtil.isEmpty(vo.getNickname())?vo.getMobile():vo.getNickname());
            userCreateReqVO.setMobile(vo.getMobile());
            userCreateReqVO.setUsername(vo.getMobile());
            userCreateReqVO.setDeptId(loginUser.getDeptId());
                userCreateReqVO.setPassword("123456");
            userId = userService.createUser(userCreateReqVO);
            Set<Long> roleList = new HashSet<>();
            //  新增用户角色关联信息   对外默认都是设计师  在项目内区分角色
            roleList.add( DesignUserRoleEnum.DESIGN.getRoleId());
            permissionService.assignUserRole(userId,roleList);
        }else{
            userId = userByMobile.getId();
        }

        // 检查好友请求

        // 校验是否已发起关联请求

        Set<Integer> statusList = relativedNcService.getUserRelStatusList(String.valueOf(userId),null);
        Set<Integer> userRelStatusList = relativedNcService.getUserRelStatusList(String.valueOf(userId),roleId.toString());
        if(!userRelStatusList.isEmpty()){
            // 关系 且角色 已存在 跳过
            return userId;
        }
        // 创建好友请求记录
        RelativedNcCreateReqVO ncCreateReqVO = new RelativedNcCreateReqVO();
        String ncStatusCd = statusList.contains(RelativedNcStatusCdEnum.USER_REL_STATUS_CD_1.getCode())?
                RelativedNcStatusCdEnum.USER_REL_STATUS_CD_1.getCode().toString():
                RelativedNcStatusCdEnum.USER_REL_STATUS_CD_0.getCode().toString();

        ncCreateReqVO.setStatusCd(ncStatusCd);
        ncCreateReqVO.setUserId(String.valueOf(loginUserId));
        ncCreateReqVO.setRelId(String.valueOf(userId));
        ncCreateReqVO.setRoleId(vo.getRoleId());
        ncCreateReqVO.setStartTime(new Date());
        ncCreateReqVO.setRemarkName(StrUtil.isEmpty(vo.getRemarkName())?vo.getNickname():vo.getRemarkName());
        // 创建请求记录
        relativedNcService.createRelativedNc(ncCreateReqVO);
//        存在有效记录 直接发起正向好友数据
        if(  statusList.contains(RelativedNcStatusCdEnum.USER_REL_STATUS_CD_1.getCode())){
            //  发起人正向数据
            RelativedDO relativedDO = new RelativedDO();
            relativedDO.setNickName(vo.getRemarkName());
            relativedDO.setUserId(String.valueOf(loginUserId));
            relativedDO.setRelUserId(String.valueOf(userId));
            relativedDO.setRelationStatus(ncStatusCd);
            relativedDO.setRelUserCd(vo.getRoleId());
            relativedMapper.insert(relativedDO);
        }


        return userId;
    }

    /**
     * 新增项目风格类型
     *
     * @param styleCd 项目风格
     * @return 项目风格
     */
    @Override
    public Long createStyleCd(String styleCd) {
         checkDictTypeValid("style_cd");
        DictDataSaveReqVO vo = new DictDataSaveReqVO();
        vo.setStatus(CommonStatusEnum.ENABLE.getStatus());
        vo.setColorType("default");
        vo.setLabel(styleCd);
        vo.setDictType("style_cd");
        vo.setValue(styleCd);
        vo.setLabel(styleCd);
        vo.setRemark(styleCd);
        return dictDataService.createDictData(vo);
    }


    public DictTypeDO checkDictTypeValid(String type) {
        DictTypeDO dictType = dictTypeMapper.selectByType(type);
        if (dictType == null) {
            throw exception(DICT_TYPE_NOT_EXISTS);
        }
        if (!CommonStatusEnum.ENABLE.getStatus().equals(dictType.getStatus())) {
            throw exception(DICT_TYPE_NOT_ENABLE);
        }

        return dictType;
    }


    /**
     * 获取装修记录的时间、节点以及图片信息
     * @param id
     * @return
     */
    @Override
    public List<HouseNodeDateVO> getHouseNodeAndUrl(Long id) {
        // 获取当前登录人员
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        //判断当前登录人员是否有权限
        QueryWrapper<HouseUserRelDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",loginUserId);
        queryWrapper.eq("status","0");
        //无权限返回错误信息
        if (houseUserRelMapper.selectOne(queryWrapper)==null){
            throw exception(QUERY_NOT_EXISTS);
        }
        //有权限则查询节点图片信息
        List<Map> picUrlNode = picMapper.getPicUrlByHouseId(String.valueOf(id));
        if (picUrlNode.isEmpty()){
            return new ArrayList<>();
        }

        List<HouseNodeDateVO> houseNodeDateVOList = new ArrayList<>();
        //循环取值组装返回报文格式
        for (Map map:picUrlNode){
            for (int i=0;i<houseNodeDateVOList.size();i++){
                if (map.get("date").equals(houseNodeDateVOList.get(i))){
                    //如果已经存在日期了，就直接放节点和图片信息即可
                    HouseNodeAndUrlVO houseNodeAndUrlVO = new HouseNodeAndUrlVO();
                    houseNodeAndUrlVO.setNodeId(String.valueOf(map.get("nodeId")));
                    houseNodeAndUrlVO.setNodeName(String.valueOf(map.get("nodeName")));
                    houseNodeAndUrlVO.setUrl(String.valueOf(map.get("url")));

                    houseNodeDateVOList.get(i).getHouseNodeAndUrlVOList().add(houseNodeAndUrlVO);
                }else {
                    //如果不存在该日期，则new一个实体类
                    List<HouseNodeAndUrlVO> houseNodeAndUrlVOList= new ArrayList<>();
                    HouseNodeAndUrlVO houseNodeAndUrlVO = new HouseNodeAndUrlVO();
                    houseNodeAndUrlVO.setNodeId(String.valueOf(map.get("nodeId")));
                    houseNodeAndUrlVO.setNodeName(String.valueOf(map.get("nodeName")));
                    houseNodeAndUrlVO.setUrl(String.valueOf(map.get("url")));
                    houseNodeAndUrlVOList.add(houseNodeAndUrlVO);

                    HouseNodeDateVO houseNodeDateVO = new HouseNodeDateVO();
                    SimpleDateFormat sdf = new SimpleDateFormat(DateUtils.FORMAT_YEAR_MONTH_DAY);
                    try {
                        houseNodeDateVO.setDate(sdf.parse(String.valueOf(map.get("date"))));
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    houseNodeDateVO.setHouseNodeAndUrlVOList(houseNodeAndUrlVOList);
                    houseNodeDateVOList.add(houseNodeDateVO);
                }
            }
        }
        return houseNodeDateVOList;
    }

    /**
     * 关闭项目
     * @暂不考虑重启 项目
     * @param id houseId主键
     */
    @Override
    public void closeHouse(Long id) {
        final Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        // 先判断当前操作人是否是项目的关联人(状态正常)  不是 报错
        final HouseDO houseDO = houseMapper.selectById(id);
        if(!loginUserId.toString().equals(houseDO.getCreator())){
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.USER_NOT_CREATE_PROJECT);
        }
        final String nowDate = DateUtil.formatChineseDate(new Date(), false, false);
        // 是 则 1.关闭 当前房屋的所有状态为进行中   流程任务  / 便于后续重启项目操作
        QueryWrapper<FlowTaskDO> updateFlowTaskWrapper = new QueryWrapper<>();
        FlowTaskDO updateDo = new FlowTaskDO();
//        set
        updateDo.setStatusCd(FlowStatusEnum.FLOW_STATUS_ENUM_2.getCode());
        updateDo.setRemark("项目于"+ nowDate+" 中止;");
//        where
        updateFlowTaskWrapper.eq("house_id",id);
        updateFlowTaskWrapper.eq("status_cd", FlowStatusEnum.FLOW_STATUS_ENUM_1.getCode());
        flowTaskMapper.update(updateDo,updateFlowTaskWrapper);
        //  2.关闭项目申请  项目申请在 流程任务中 taskType=2  在第一步已经关闭
        // 关闭 所有问题
        QueryWrapper<ProblemDO> updateProblemWrapper = new QueryWrapper<>();
        ProblemDO problemDO = new ProblemDO();
        problemDO.setStatus(String.valueOf(ProblemStatusCdEnum.PROBLEM_STATUS_CD_ENUM_3.getCode()));
        problemDO.setRemark("项目于"+ nowDate+" 中止;");
        updateProblemWrapper.eq("house_id",id);
        updateProblemWrapper.eq("status", ProblemStatusCdEnum.PROBLEM_STATUS_CD_ENUM_1.getCode());
        problemMapper.update(problemDO,updateProblemWrapper);

        //  3.所有节点状态改为终止
        QueryWrapper<NodeDO> updateNodeWrapper = new QueryWrapper<>();
        NodeDO updateNodeDo = new NodeDO();
        updateNodeDo.setStatusCd(String.valueOf(NodeStatusEnum.NODE_STATUS_ENUM_3.getCode()));
        updateNodeDo.setRemark("项目于"+ nowDate+" 中止;");
        updateNodeWrapper.eq("house_id",id);
        updateNodeWrapper.eq("status_cd", NodeStatusEnum.NODE_STATUS_ENUM_1.getCode());
        nodeMapper.update(updateNodeDo,updateNodeWrapper);

        //  4.所有流程状态改为终止
        QueryWrapper<FlowDO> updateFlowWrapper = new QueryWrapper<>();
        FlowDO updateFlowDo = new FlowDO();
        updateFlowDo.setStatusCd(FlowStatusEnum.FLOW_STATUS_ENUM_3.getCode());
        updateFlowDo.setRemark("项目于"+ nowDate+" 中止;");
        updateFlowWrapper.eq("house_id",id);
        updateFlowWrapper.eq("status_cd", FlowStatusEnum.FLOW_STATUS_ENUM_1.getCode());
        flowMapper.update(updateFlowDo,updateFlowWrapper);

        //  5.房屋状态改为终止
        houseDO.setStatus(String.valueOf(HouseStatusCdEnum.HOUSE_STATUS_CD_2.getCode()));
        houseMapper.updateById(houseDO);
    }

    /**
     * 新增供应商负责人并新增登录用户
     *
     * @param vo
     */
    @Override
    public Long createPrincipalUserRel(HousePrincipalUserRelVO vo) {
        // 查询采购流程
        HouseUserRelVO houseUserRelVO = BeanUtil.copyProperties(vo, HouseUserRelVO.class);
        // 创建好友请求
        Long userId = createUserRel(houseUserRelVO);

        // 判断供应商是否已在项目中
        List<HouseUserRelDO> userRoleList = houseUserRelService.
                getHouseUserRelByHouseIdAndUserIdAndRoleId(vo.getHouseId(), userId, Long.valueOf(vo.getRoleId()));
        if(userRoleList.size()>0){
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.GYS_USER_ID_EXITS);
        }
        HouseRespVO houseById = getHouseById(vo.getHouseId());
        //  项目关联任务初始化为待开始 ,  待好友通过后  自动改为进行中
        saveHouseUserRelTask(vo.getHouseId(),houseById.getProjectName(),userId,Long.valueOf(vo.getRoleId())
                ,UserRelStatusCdEnum.USER_REL_STATUS_CD_0.getCode());
        // 关联好友关系建立
        HouseUserRelDO houseUserRel = new HouseUserRelDO();
        houseUserRel.setHouseId(houseById.getId());
        houseUserRel.setUserId(userId);
        houseUserRel.setStatus(UserRelStatusCdEnum.USER_REL_STATUS_CD_1.getCode().toString());
        houseUserRel.setRoleId(Long.valueOf(vo.getRoleId()));
        houseUserRel.setDeleted(false);
        houseUserRelMapper.insert(houseUserRel);
        // 添加到userFlowRel 表
        saveHouseUserFlowRel(vo.getHouseId(),vo.getFlowId(),userId,Long.valueOf(vo.getRoleId()));
        // 发送微信好友消息通知提醒
        return userId;
    }



    public List<PicDO> getPicDataList(Long houseId,List<String> sourceTypes){

        return picService.getPicData(houseId,sourceTypes);
    }

    /**
     * 保存家庭用户关系
     *
     * @param vo 家庭用户关系请求对象
     */
    @Override
    public void saveFamilyUserRel(HouseUserRelFamilyReqVO vo) {
        // 校验项目id 是否存在
        validateHouseExists(vo.getId());
        // 校验用户是否存在

        // 新增用户

        // 创建好友请求 默认已同意

        // 创建项目关联请求 角色为亲友 状态为已同意


    }

}
